package com.example.oj.service.impl;

import cn.hutool.json.JSONUtil;
import com.example.oj.entity.Question;
import com.example.oj.entity.Submit;
import com.example.oj.service.*;
import com.example.ojcommon.common.*;
import com.example.ojcommon.enums.LanguageEnum;
import com.example.ojcommon.enums.SubmitReturnEnum;
import com.example.ojcommon.exception.BusinessException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class JudgeServiceImpl implements JudgeService {

    @Resource
    private QuestionService questionService;

    @Resource
    private SubmitService submitService;

    @Resource
    private UserService userService;

    @Override
    public void doJudge(ExecuteCodeResponse response) {
        //1.查询题目
        Long questionId = response.getQuestionId();
        Question question = questionService.getById(questionId);
        //2.查询提交记录
        Long submitId = response.getSubmitId();
        Submit submit = submitService.getById(submitId);
        //3.执行判题逻辑
        JudgeInfo judgeInfo = response.getJudgeInfo();
        judgeInfo = checkJudge(question, submit, judgeInfo);
        //4.将结果封装到题目提交实体
        submit.setJudgeInfo(JSONUtil.toJsonStr(judgeInfo));
        submit.setStatus(3);
        //5.修改题目提交信息
        boolean b = submitService.updateById(submit);
        if (!b) {
            throw new BusinessException(ErrorCode.API_REQUEST_ERROR,"无法修改题目提交信息");
        }
        //6.修改题目通过数
        questionService.updateQuestionNum(questionId);
        userService.updateUserSubmitNum(submit.getUserId());
    }

    public JudgeInfo checkJudge(Question question, Submit submit, JudgeInfo judgeInfo) {
        SubmitReturnEnum message = judgeInfo.getMessage();
        Long memory = judgeInfo.getMemory();
        Long time = judgeInfo.getTime();
        List<String> resultList = judgeInfo.getResultList();
        //如果返回信息不为null,说明发生了异常，这里就直接返回
        if (message != null) {
            return judgeInfo;
        }
        //判断输出用例和预期输出用例是否相等
        List<JudgeCase> judgeCase = JSONUtil.toList(question.getJudgeCase(), JudgeCase.class);
        List<String> outputList = judgeCase.stream().map(JudgeCase::getOutput).collect(Collectors.toList());
        if (outputList.size() != resultList.size()) {
            judgeInfo.setMessage(SubmitReturnEnum.ANSWER_WRONG);
            return judgeInfo;
        }
        for (int i = 0; i < resultList.size(); i++) {
            if (!outputList.get(i).equals(resultList.get(i))) {
                judgeInfo.setMessage(SubmitReturnEnum.ANSWER_WRONG);
                return judgeInfo;
            }
        }
        //判断题目是否满足时间和内存限制
        JudgeConfig judgeConfig = JSONUtil.toBean(question.getJudgeConfig(), JudgeConfig.class);
        if (time > judgeConfig.getTimeLimit()) {
            judgeInfo.setMessage(SubmitReturnEnum.TIMEOUT);
            return judgeInfo;
        }
        if (memory > judgeConfig.getMemoryLimit()) {
            judgeInfo.setMessage(SubmitReturnEnum.MEMORY_OUT);
            return judgeInfo;
        }
        judgeInfo.setMessage(SubmitReturnEnum.ACCEPTED);
        return judgeInfo;
    }

}
